package com.Jshop.cart.filter;

import com.Jshop.cart.config.JwtProperties;
import com.Jshop.cart.entity.UserInfo;
import com.Jshop.cart.utils.JwtUtils;
import com.Jshop.common.utils.CookieUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 购物车模块 判断用户登录状态的拦截器
 * 利用存储在购物车的RSA公钥进行token解析 验证有效性
 * */
public class LoginInterceptor extends HandlerInterceptorAdapter {

    //这玩意是在MvcConfig里进行的实例化
    private JwtProperties jwtProperties;

    //构造器
    public LoginInterceptor(JwtProperties jwtProperties) {
        this.jwtProperties = jwtProperties;
    }

    // ThreadLocal的一个实际应用
    //定义一个线程域，存放登录用户
    private static final ThreadLocal<UserInfo> tl = new ThreadLocal<>();



    /**
     * 解析token 若能成功解析出用户载荷信息，放入ThreadLocal（用户名（回显） id）中进行存储，后续该请求就不用去查询数据库了
     * 前置拦截 自动拦截
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

        //根据请求的cookie查询token
        String token = CookieUtils.getCookieValue(request, "LY_TOKEN");

        //未登录 返回401
        if (StringUtils.isBlank(token)){
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }

        //查询用户信息
        try {
            //解析token中的用户信息
            UserInfo user = JwtUtils.getInfoFromToken(token, jwtProperties.getPublicKey());
            //放入线程域ThreadLocal 方便该请求后续读取
            tl.set(user);
            return true;
        }catch (Exception e){
            //抛出异常，返回401
            response.setStatus(HttpStatus.UNAUTHORIZED.value());
            return false;
        }

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //防止内存溢出 及时释放ThreadLocal
        tl.remove();
    }

    //从ThreadLocal获取User
    //静态方法
    public static UserInfo getLoginUser() {
        return tl.get();
    }

}
